package be.kuleuven.cs.mop;


import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import be.kuleuven.cs.mop.app.System;
import be.kuleuven.cs.mop.app.controllers.Controllers;
import be.kuleuven.cs.mop.app.controllers.UserController;
import be.kuleuven.cs.mop.domain.exceptions.InvalidCurrentUserException;
import be.kuleuven.cs.mop.domain.exceptions.TaskManagerException;
import be.kuleuven.cs.mop.domain.model.impl.Field;
import be.kuleuven.cs.mop.domain.model.impl.FieldType;
import be.kuleuven.cs.mop.domain.model.impl.Interval;
import be.kuleuven.cs.mop.domain.model.impl.ProjectImpl;
import be.kuleuven.cs.mop.domain.model.impl.ResourceImpl;
import be.kuleuven.cs.mop.domain.model.impl.ResourceTypeImpl;
import be.kuleuven.cs.mop.domain.model.impl.Schedule;
import be.kuleuven.cs.mop.domain.model.impl.TaskImpl;
import be.kuleuven.cs.mop.domain.model.impl.TaskTypeImpl;
import be.kuleuven.cs.mop.domain.model.impl.UserImpl;
import be.kuleuven.cs.mop.domain.model.impl.UserTypeImpl;
import be.kuleuven.cs.mop.domain.model.impl.World;



public final class TestEnvironment {
	
	public final UserImpl				admin;
	public final UserTypeImpl			adminType;
	
	public final Controllers			controllers;
	
	public final GregorianCalendar		datum1;
	public final GregorianCalendar		datum2;
	public final GregorianCalendar		datum3;
	
	public final long					duration		= (15 * 60000L);
	

	public final Field					field1;
	public final Field					field2;	
	public final HashMap<String, Field>	fields			= new HashMap<String, Field>();

	
	public final ResourceImpl			resource1;
	public final List<ResourceTypeImpl>	resourceTypes	= new ArrayList<ResourceTypeImpl>();
	public final ResourceTypeImpl		invalidResourceType;
	
	public final ProjectImpl			project1;
	
	public final Schedule				schedule1;
	public final System					system;
	
	public final TaskImpl				task1;
	public final List<TaskTypeImpl>		taskTypes		= new ArrayList<TaskTypeImpl>();
	
	public final TaskTypeImpl			testTaskType;
	
	public final UserImpl				user1;
	public final UserImpl				user2;
	public final List<UserTypeImpl>		userTypes		= new ArrayList<UserTypeImpl>();
	
	public final World					world			= new World();
	
	
	private TestEnvironment() throws TaskManagerException {
		datum1 = new GregorianCalendar(2012, 5, 1, 0, 0);
		datum2 = new GregorianCalendar(2012, 6, 8);
		datum3 = new GregorianCalendar(2012, 5, 1, 0, 30);
		
		invalidResourceType	=  new ResourceTypeImpl(new World(), "Chalkboard");
		
		project1 = new ProjectImpl(world, "TestProject 1");
		field1 = new Field(FieldType.TEXTUAL, new String("TaskManTask"));
		Integer randomInt = 5;
		field2 = new Field(FieldType.NUMERICAL, randomInt);
		fields.put("Name", field1);
		
		

		
		resourceTypes.add(new ResourceTypeImpl(world, "TestResourceTypeA"));
		resourceTypes.add(new ResourceTypeImpl(world, "TestResourceTypeB"));
		resource1 = new ResourceImpl(world, "TestResource", resourceTypes.get(0));

		
		system		= new System(world);
		controllers	= new Controllers(system);
		
		adminType	= world.getUserTypes().get(0);	// new AdminUserTypeImpl(world);
		admin		= world.getUsers().get(0);	// new UserImpl(world, "Admin", adminType);
		
		userTypes.add(adminType);
		userTypes.add(new UserTypeImpl(world, "TestUserType"));
		user1 = new UserImpl(world, "TestUser",		userTypes.get(1));
		user2 = new UserImpl(world, "TestUser 2",	userTypes.get(1));
		
		schedule1 = new Schedule(datum1, datum2, duration);
//		fields.put("Name", new Field(FieldType.TEXTUAL, new String("TaskManTask")));
		
		taskTypes.add(new TaskTypeImpl(system.getWorld(), "TestTask",
				new HashSet<UserTypeImpl>(userTypes),
				new HashMap<UserTypeImpl, Interval>(),
				new HashMap<String, FieldType>(),
				new HashMap<ResourceTypeImpl, Interval>()));
		task1 = user1.createTask(schedule1,
				new HashSet<TaskImpl>(),
				new HashMap<String, Field>(),
				taskTypes.get(0));
		
		final UserController cUsers = controllers.getControllerUsers();
		cUsers.setUser(admin);
		try {
			cUsers.setUser(cUsers.createUser("TEST_USER", userTypes.get(1)));
		} catch (final InvalidCurrentUserException e) {
			//	should never be reached
			assert false : e;
			throw new RuntimeException();
		}
		
		testTaskType	= taskTypes.get(0);
	}
	
	
	
	public static final TestEnvironment newInstance() {
		try {
			return new TestEnvironment();
		} catch (final Exception e) {
			e.printStackTrace();
			assert false : e;
			throw new InternalError(e.getMessage());
		}
	}
	
}